﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System;

namespace tcp
{
    class Server {
        private Socket listen_sock_ = null;
        private Socket client_sock_ = null;
        private int port_;

        public Server(int port) {
            port_ = port;
            IPEndPoint ip = new IPEndPoint(IPAddress.Any, 6389);
            listen_sock_ = new Socket(ip.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
            listen_sock_.Bind(ip);
            listen_sock_.Listen(100);
        }

        public void accept() {
            if(listen_sock_!=null)
                client_sock_ = listen_sock_.Accept();
        }

        public string read() {
            string recv = string.Empty;
            if (client_sock_ != null)
            {
                //Initialize a buffer to hold the received data
                byte[] buffer = new byte[client_sock_.ReceiveBufferSize];
                //There is no accurate method for checking how many bytes are read
                //unless you check the return from the Read method
                int bytesRead = client_sock_.Receive(buffer,0);
                //For the example assume the data we are received is ASCII data.
                recv = Encoding.ASCII.GetString(buffer, 0, bytesRead);
            }
            return recv;
        }

        public int write(string data) {
            return client_sock_.Send(Encoding.UTF8.GetBytes(data));
        }
    }

    class Client {
        Socket conn_ = null;
        String ip_ = null;
        int port_ = 0;
        public Client(string ip, int port) {
            ip_ = ip;
            port_ = port;
            IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse(ip_), 6389);
            conn_ = new Socket(endpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
            conn_.Connect(endpoint);
        }

        public string read() {
            string recv = string.Empty;
            if (conn_ != null)
            {
                //Initialize a buffer to hold the received data
                byte[] buffer = new byte[conn_.ReceiveBufferSize];
                //There is no accurate method for checking how many bytes are read
                //unless you check the return from the Read method
                int bytesRead = conn_.Receive(buffer, 0);
                //For the example assume the data we are received is ASCII data.
                recv = Encoding.ASCII.GetString(buffer, 0, bytesRead);
            }
            return recv;

        }

        public int write(string data) {
            return conn_.Send(Encoding.UTF8.GetBytes(data));
        }
    }

    /// <summary>
    /// 这里封装了一对服务器和客户端，然后通过两个线程来分别使用他们，实现通信。
    /// </summary>
    class Program
    {
        private static void server_handler() {
            Server server = new Server(10000);
            server.accept();
            while (true)
            {
                string recv = server.read();
                System.Console.WriteLine(String.Format("Server Recv > {0}",recv));
                server.write(DateTime.Now.ToString());
            }
        }

        private static void client_handler() {
            Client client = new Client("127.0.0.1",10000);
            while (true) {
                client.write("Request Time");
                string recv = client.read();
                System.Console.WriteLine(string.Format("Client Recv > {0}",recv));
                Thread.Sleep(1000);
            }
        }
        static void Main(string[] args)
        {
            /*******Create two thread, one for send, one for recive.********/
            //Create server thread
            Thread server_thread = new Thread(new ThreadStart(server_handler));
            server_thread.Start();
            //Create client thread
            Thread client_thread = new Thread(new ThreadStart(client_handler));
            client_thread.Start();
            //Wait end
            server_thread.Join();
        }
    }
}